package com.bookmall.member.web;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.bookmall.common.constant.DefaultDataConstants;
import com.bookmall.common.constant.ExceptionTypeConstants;
import com.bookmall.common.entity.to.MemberInfoTo;
import com.bookmall.common.exception.LoginException;
import com.bookmall.member.domain.MemberInfo;
import com.bookmall.member.domain.vo.LoginUserVo;
import com.bookmall.member.service.IMemberInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Author 胡菜鸡
 * @Create 2022-04-02-9:19
 */
@Controller
@RequestMapping("/member/web")
public class LoginController {
    @Autowired
    private IMemberInfoService memberInfoService;

    @PostMapping("/login")
    public String login(@Valid LoginUserVo loginUserVo, BindingResult result,
                        RedirectAttributes redirectAttributes, HttpSession session){
        //如果 @Valid 的表单校验不通过
        if(result.hasErrors()){
            //将错误信息收集起来以map形式返回给注册页面
            Map<String, String> errors = new HashMap<>();
            for (FieldError fieldError : result.getFieldErrors()) {
                errors.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
            //重定向携带数据（携带的数据被取出后就会就会删除，因此会有分布式多线程问题）
            //TODO 解决分布式问题
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:/login.html";
        }

        /*
            真正的登录
         */
        try {
            MemberInfo account = memberInfoService.login(loginUserVo);
            MemberInfoTo memberInfoVo = new MemberInfoTo();
            BeanUtils.copyProperties(account, memberInfoVo);
            //登录成功，共享session数据
            session.setAttribute(DefaultDataConstants.LOGIN_USER, memberInfoVo);
            System.out.println(session.getId());
            //前往首页
//            return "redirect:http://huyulu666.top:10000/index.html";
            return "redirect:http://huyulu666.top/index.html";
        } catch (LoginException e){
            Map<String,String> errors = new HashMap<>();
            //出现登录异常，则将异常信息发送回去
            if(e.getCode().equals(ExceptionTypeConstants.ACCOUNT_NOT_EXIST)){
                errors.put("username", e.getMessage());
            } else if(e.getCode().equals(ExceptionTypeConstants.PASSWORD_ERROR)){
                errors.put("password", e.getMessage());
            }
            //返回错误信息
            redirectAttributes.addFlashAttribute("errors", errors);

            //将原先填入表格的数据也发送回去
            Map<String, String> data = new HashMap<>();
            for (Field field : loginUserVo.getClass().getDeclaredFields()) {
                field.setAccessible(true);
                try {
                    data.put(field.getName(), StringUtils.toStringTrim(field.get(loginUserVo)));
                } catch (IllegalAccessException ex) {
                    ex.printStackTrace();
                    errors.put("username", "登录出错，获取属性值失败");
                }
            }
            //返回数据信息
            redirectAttributes.addFlashAttribute("data", data);
            return "redirect:/login.html";
        }
    }

    @DeleteMapping("/logout")
    public String logout(HttpServletRequest request, RedirectAttributes redirectAttributes){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println(cookie.getName());
        }
        return "ok";
    }
}
